package org.noote.libs.widget;

import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

public class Widget_Window {

	protected int _iID = 0;
	protected static int _iWindowID = 0;
	protected long _uData = 0;
	
	protected Widget_Window _parent = null;
	protected ArrayList<Widget_Window> _children = new ArrayList<Widget_Window>();

	public static int TOUCH_RELEASED = 0;
	public static int TOUCH_PRESSED = 1;
	public static int TOUCH_MOVED = 2;

	protected int _iMin_X = 0, _iMin_Y = 0;
	protected int _iMax_X = 128, _iMax_Y = 128;

	protected int _iState = 0;
	protected float _fTouch_X = 0, _fTouch_Y = 0;
	protected int _iTouch_X = 0, _iTouch_Y = 0;

	WidgetEvent_OnTouch _eventOnTouch = null;
	WidgetEvent_OnClick _eventOnClick = null;
	
	protected boolean _bNewEvent = false;
	protected int _iTouchID = -1;
	
	protected int _iOldState = 0;
	protected float _fOldTouch_X = 0, _fOldTouch_Y = 0;

	protected WidgetTheme _theme = null;
	
	protected WidgetSquare2D _squareBackground = null;
	protected int _iBackgroundPosition_X = 0, _iBackgroundPosition_Y = 0;
	protected float _colorBackground[] = {0.3f, 0.62f, 1, 1};
	protected float _colorSelectedBackground[] = {0.4f, 0.8f, 1.0f, 1};
	protected float _colorDisabledBackground[] = {0.65f, 0.65f, 0.7f, 1};
	
	protected boolean _bEnabled = true;
	protected boolean _bSelected = false;
	
	public Widget_Window(Widget_Window parent) {
		_iID = _iWindowID++;
		_parent = parent;
		if(parent != null)
			_theme = parent._theme;
	}
	
	public Widget_Window(Widget_Window parent, WidgetTheme theme) {
		this(parent);
		_theme = theme;
	}
	
	public void create()
	{
		create(0, 0, 64, 64);
	}
	
	public void create(int x, int y, int sx, int sy)
	{
		setWorkSpace(x, y, sx, sx);
		
		if(_theme != null)
		{
			_colorBackground = _theme.colorSkinDefault;
			_colorSelectedBackground = _theme.colorSkinSelected;
			_colorDisabledBackground = _theme.colorSkinDisabled;
		}
		
		refresh();
	}
	
	public boolean add(Widget_Window window)
	{
		if(_children.add(window))
		{
			refresh();
			return true;
		}
		return false;
	}
	
	public void setWorkSpace(int x, int y, int sx, int sy) {
		_iMin_X = x;
		_iMin_Y = y;
		_iMax_X = x + sx;
		_iMax_Y = y + sy;
	}

	public void setPosition(int x, int y)
	{
		setWorkSpace(x, y, getWidth(), getHeight());
	}
	public void setSize(int sx, int sy)
	{
		setWorkSpace(getPositionX(), getPositionY(), sx, sy);
		refresh();
	}

	public void setLongData(long uData)
	{
		_uData = uData;
	}
	public long getLongData()
	{
		return _uData;
	}
	
	public void setOnClick(WidgetEvent_OnClick event)
	{
		_eventOnClick = event;
	}
		
	public void setOnTouch(WidgetEvent_OnTouch event)
	{
		_eventOnTouch = event;
	}
	
	public boolean enableWindow(boolean bEnabled)
	{
		_bEnabled = bEnabled;
		
		for (Widget_Window window : _children) {
			window.enableWindow(_bEnabled);
		}
		
		refresh();
		
		return isEnabled();
	}
	public boolean isEnabled()
	{
		return _bEnabled;
	}
	
	public boolean isInWorkSpace(int x, int y) {
		if (x >= _iMin_X && x <= _iMax_X && y >= _iMin_Y && y <= _iMax_Y)
			return true;

		return false;
	}

	public boolean setTouchEvent(int x, int y, int id, int state) {
		
		if(!_bEnabled) return false;
		
		for(Widget_Window window : _children)
		{
			//if(window.setTouchEvent(x-_iMin_X, y-_iMin_Y, id, state)) return true;
			//window.setTouchEvent(x-_iMin_X, y-_iMin_Y, id, state);
			window.setTouchEvent(x, y, id, state);
		}
		
		// toujours dans l'espace de travail
		if (isInWorkSpace(x, y)) {
			
			// this is not for this pressed button ?
			if (_iState == TOUCH_RELEASED)
				_iTouchID = id;
			else if (_iTouchID != id)
				return false;

			// stock old state
			_iOldState = _iState;
			_fOldTouch_X = _fTouch_X;
			_fOldTouch_Y = _fTouch_Y;

			// new state
			_iState = state;
			
			_iTouch_X = x - _iMin_X;
			_iTouch_Y = y - _iMin_Y;
			
			// calcul touch position
			_fTouch_X = ((float) (_iTouch_X) / (float) (_iMax_X - _iMin_X));
			_fTouch_Y = ((float) (_iTouch_Y) / (float) (_iMax_Y - _iMin_Y));

			_checkButtons();
			_checkEvents();
			
			return true;
		}
		// out of workspace ?
		else if (_iTouchID > -1 && _iTouchID == id) {
			_iTouchID = -1;
			if (_iState != TOUCH_RELEASED) {
				_iState = TOUCH_RELEASED;
			}

			_checkButtons();
			_checkEvents();
		}
		
		return false;
	}

	public void reset() {
		_bNewEvent = true;
		_fTouch_X = 0;
		_fTouch_Y = 0;
		_iState = TOUCH_RELEASED;
		_iTouchID = -1;

		_checkButtons();
	}

	protected void _checkButtons() {

	}
	
	protected void _checkEvents() {
		
		if(_eventOnClick != null && haveNewEvent() && _iState==TOUCH_PRESSED)
		{
			if(_eventOnClick.onClick(this))
				resetNewEvent();
		}
		if(_eventOnTouch != null && haveNewEvent())
		{
			if((_iState==TOUCH_PRESSED && _eventOnTouch.onPressed(this))
					|| (_iState==TOUCH_MOVED && _eventOnTouch.onMoved(this))
					|| (_iState==TOUCH_RELEASED && _eventOnTouch.onReleased(this)))
				resetNewEvent();
		}
	}

	public boolean haveNewEvent() {
		return _bNewEvent;
	}

	public void resetNewEvent() {
		_bNewEvent = false;
	}

	public float getTouchX() {
		return _fTouch_X;
	}

	public float getTouchY() {
		return _fTouch_Y;
	}

	public int getPositionX()
	{
		return _iMin_X; 
	}
	
	public int getPositionY()
	{
		return _iMin_Y; 
	}
	
	public int getWidth()
	{
		return (_iMax_X - _iMin_X); 
	}
	
	public int getHeight()
	{
		return (_iMax_Y - _iMin_Y); 
	}
	
	public boolean isPressed()
	{
		return (_iState == TOUCH_PRESSED);
	}
	public boolean isReleased()
	{
		return (_iState == TOUCH_RELEASED);
	}
	
	public void select(boolean bSelect) {
		select(bSelect, true);
	}
	public void select(boolean bSelect, boolean bPropagate) {
		_bSelected = bSelect;
		if(bPropagate)
		{
			for (Widget_Window window : _children) {
				window.select(_bSelected);
			}
		}
		refresh();
	}
	public boolean isSelected() {
		return _bSelected;
	}
	
	public void setBackground(int texID) {
		if (_squareBackground == null)
			_squareBackground = new WidgetSquare2D(texID);
		else
			_squareBackground.setTextureID(texID);
		refresh();
	}
	public void setBackgroundColor(float color[]) {
		_colorBackground = color;
		refresh();
	}
	public void setBackgroundColor(float r, float g, float b) {
		setBackgroundColor(r, g, b, 1.0f);
	}
	public void setBackgroundColor(float r, float g, float b, float a) {
		float color[] = {r, g, b, a};
		setBackgroundColor(color);
	}

	public void refresh()
	{
		 _preRefresh();
		 _refreshElement();
		 _postRefresh();
	}
	
	protected void _preRefresh()
	{
	}
	protected void _refreshElement()
	{
		if (_squareBackground != null)
		{
			_squareBackground.setSize(getWidth(), getHeight(), 0);
		}
		
		for (Widget_Window window : _children) {
			window.refresh();
		}
	}
	protected void _postRefresh()
	{
		if (_squareBackground != null)
		{
			if(_bEnabled && _bSelected)
				_squareBackground.setColor(_colorSelectedBackground);
			else if(_bEnabled)
				_squareBackground.setColor(_colorBackground);
			else
				_squareBackground.setColor(_colorDisabledBackground);
		}
	}
	
	// fun stuff OGL :)
	public void draw(GL10 gl, float fDepth) {
		_preDraw(gl, fDepth);
		_drawElements(gl, fDepth);
		_postDraw(gl);
	}
	
	protected void _preDraw(GL10 gl, float fDepth) {		
		gl.glPushMatrix();
		gl.glTranslatef(_iMin_X, _iMin_Y, fDepth);

		gl.glDisable(GL10.GL_DEPTH_TEST);
	}

	protected void _drawElements(GL10 gl, float fDepth) {
		if (_squareBackground != null) {
			
			gl.glPushMatrix();
			gl.glTranslatef(_iBackgroundPosition_X, _iBackgroundPosition_Y, fDepth);
			_squareBackground.draw(gl);
			gl.glPopMatrix();
		}
		
		for (Widget_Window window : _children) {
			window.draw(gl, 0);
		}
	}

	protected void _postDraw(GL10 gl) {
		gl.glEnable(GL10.GL_DEPTH_TEST);	

		gl.glPopMatrix();
	}

}
